package top.lichunsheng.minio;

import com.google.common.collect.Multimap;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Part;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

@Slf4j
public class PearlMinioClient extends MinioClient {

    private static final String UPLOAD_ID = "uploadId";

    public PearlMinioClient(MinioClient client) {
        super(client);
    }

    /**
     * 创建分片上传请求
     *
     * @param bucketName       存储桶
     * @param region           区域
     * @param objectName       对象名
     * @param headers          消息头
     * @param extraQueryParams 额外查询参数
     */
    @Override
    protected CreateMultipartUploadResponse createMultipartUpload(String bucketName, String region, String objectName, Multimap<String, String> headers, Multimap<String, String> extraQueryParams) throws NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, ServerException, XmlParserException, ErrorResponseException, InternalException, InvalidResponseException {
        return super.createMultipartUpload(bucketName, region, objectName, headers, extraQueryParams);
    }

    /**
     * 完成分片上传，执行合并文件
     *
     * @param bucketName       存储桶
     * @param region           区域
     * @param objectName       对象名
     * @param uploadId         上传ID
     * @param parts            分片
     * @param extraHeaders     额外消息头
     * @param extraQueryParams 额外查询参数
     */
    @Override
    public ObjectWriteResponse completeMultipartUpload(String bucketName, String region, String objectName, String uploadId, Part[] parts, Multimap<String, String> extraHeaders, Multimap<String, String> extraQueryParams) throws NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, ServerException, XmlParserException, ErrorResponseException, InternalException, InvalidResponseException {
        return super.completeMultipartUpload(bucketName, region, objectName, uploadId, parts, extraHeaders, extraQueryParams);
    }

    /**
     * 查询分片数据
     *
     * @param bucketName       存储桶
     * @param region           区域
     * @param objectName       对象名
     * @param uploadId         上传ID
     * @param extraHeaders     额外消息头
     * @param extraQueryParams 额外查询参数
     */
    public ListPartsResponse listMultipart(String bucketName, String region, String objectName, Integer maxParts, Integer partNumberMarker, String uploadId, Multimap<String, String> extraHeaders, Multimap<String, String> extraQueryParams) throws NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, ServerException, XmlParserException, ErrorResponseException, InternalException, InvalidResponseException {
        return super.listParts(bucketName, region, objectName, maxParts, partNumberMarker, uploadId, extraHeaders, extraQueryParams);
    }

    /**
     * 经检查 2021-02-04前的版本此方法有bug 看过社区新版本已经修复，这里不改版本了，重写
     *
     * @param bucketName
     * @param region
     * @param objectName
     * @param maxParts
     * @param partNumberMarker
     * @param uploadId
     * @param extraHeaders
     * @param extraQueryParams
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InsufficientDataException
     * @throws IOException
     * @throws InvalidKeyException
     * @throws ServerException
     * @throws XmlParserException
     * @throws ErrorResponseException
     * @throws InternalException
     * @throws InvalidResponseException
     */
    public CustomListPartsResponse customListParts(String bucketName, String region, String objectName, Integer maxParts, Integer partNumberMarker, String uploadId, Multimap<String, String> extraHeaders, Multimap<String, String> extraQueryParams) throws NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, ServerException, XmlParserException, ErrorResponseException, InternalException, InvalidResponseException {

        Multimap<String, String> queryParams =
                merge(
                        extraQueryParams,
                        newMultimap(
                                UPLOAD_ID,
                                uploadId,
                                "max-parts",
                                (maxParts != null) ? maxParts.toString() : "1000"));
        if (partNumberMarker != null) {
            queryParams.put("part-number-marker", partNumberMarker.toString());
        }

        try (Response response =
                     execute(
                             Method.GET,
                             bucketName,
                             objectName,
                             getRegion(bucketName, region),
                             httpHeaders(extraHeaders),
                             queryParams,
                             null,
                             0)) {
            CustomListPartsResult result = Xml.unmarshal(CustomListPartsResult.class, response.body().charStream());
            return new CustomListPartsResponse(response.headers(), bucketName, region, objectName, result);
        }
    }
}
